package com.hog.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Hog数据源配置
 *
 * @author 糖先森
 * @date 2018年03月29日
 * @since JDK 1.8
 */
@Configuration
@EnableTransactionManagement
public class HogDataSourceConfig {
    public static final String BEAN_NAME_HOG_DATASOURCE = "hogDataSource";
    public static final String BEAN_NAME_HOG_SQL_SESSION_FACTORY = "hogSqlSessionFactory";
    public static final String BEAN_NAME_HOG_SQL_SESSION_TEMPLATE = "hogSqlSessionTemplate";
    public static final String BEAN_NAME_HOG_TRANSACTION_MANAGER = "hogTransactionManager";

    @Autowired
    private HogConnectionSetting hogConnectionSetting;

    @Value("${mybatis.xmlLocation}")
    private String xmlLocation;
    @Value("${mybatis.typeAliasesPackage}")
    private String typeAliasesPackage;

    @Bean(name = "hogDataSource")
    @Primary
    public DataSource hogDataSource() throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(this.hogConnectionSetting.getUrl());
        dataSource.setUsername(this.hogConnectionSetting.getUsername());
        dataSource.setPassword(this.hogConnectionSetting.getPassword());
        dataSource.setDriverClassName(this.hogConnectionSetting.getDriverClassName());
        dataSource.setMaxActive(this.hogConnectionSetting.getMaxActive() == null ?
                dataSource.getMaxActive() : this.hogConnectionSetting.getMaxActive());
        dataSource.setInitialSize(this.hogConnectionSetting.getInitialSize() == null ?
                dataSource.getInitialSize() : this.hogConnectionSetting.getInitialSize());
        dataSource.setMaxWait(this.hogConnectionSetting.getMaxWait() == null ?
                dataSource.getMaxWait() : this.hogConnectionSetting.getMaxWait());
        dataSource.setMinIdle(this.hogConnectionSetting.getMinIdle() == null ?
                dataSource.getMinIdle() : this.hogConnectionSetting.getMinIdle());
        dataSource.setTimeBetweenEvictionRunsMillis(this.hogConnectionSetting.getTimeBetweenEvictionRunsMillis() == null ?
                dataSource.getTimeBetweenEvictionRunsMillis() : this.hogConnectionSetting.getTimeBetweenEvictionRunsMillis());
        dataSource.setMinEvictableIdleTimeMillis(this.hogConnectionSetting.getMinEvictableIdleTimeMillis() == null ?
                dataSource.getMinEvictableIdleTimeMillis() : this.hogConnectionSetting.getMinEvictableIdleTimeMillis());
        dataSource.setValidationQuery(this.hogConnectionSetting.getValidationQuery() == null ?
                dataSource.getValidationQuery() : this.hogConnectionSetting.getValidationQuery());
        dataSource.setTestWhileIdle(this.hogConnectionSetting.getTestWhileIdle() == null ?
                dataSource.isTestWhileIdle() : this.hogConnectionSetting.getTestWhileIdle());
        dataSource.setTestOnBorrow(this.hogConnectionSetting.getTestOnBorrow() == null ?
                dataSource.isTestOnBorrow() : this.hogConnectionSetting.getTestOnBorrow());
        dataSource.setTestOnReturn(this.hogConnectionSetting.getTestOnReturn() == null ?
                dataSource.isTestOnReturn() : this.hogConnectionSetting.getTestOnReturn());
        dataSource.setPoolPreparedStatements(this.hogConnectionSetting.getPoolPreparedStatements() == null ?
                dataSource.isPoolPreparedStatements() : this.hogConnectionSetting.getPoolPreparedStatements());
        dataSource.setMaxOpenPreparedStatements(this.hogConnectionSetting.getMaxOpenPreparedStatements() == null ?
                dataSource.getMaxOpenPreparedStatements() : this.hogConnectionSetting.getMaxOpenPreparedStatements());
        dataSource.setFilters(this.hogConnectionSetting.getFilters());
        return dataSource;
    }

    @Bean(name = BEAN_NAME_HOG_SQL_SESSION_FACTORY)
    @Primary
    public SqlSessionFactory hogSqlSessionFactory(@Qualifier(BEAN_NAME_HOG_DATASOURCE) DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage(this.typeAliasesPackage);
        // 分页插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);
        Interceptor[] plugins = new Interceptor[]{pageHelper};
        sqlSessionFactoryBean.setPlugins(plugins);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(this.xmlLocation));
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject();
        sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);
        sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);
        return sqlSessionFactory;
    }

    @Bean(name = BEAN_NAME_HOG_SQL_SESSION_TEMPLATE)
    @Primary
    public SqlSessionTemplate hogSqlSessionTemplate(
            @Qualifier(BEAN_NAME_HOG_SQL_SESSION_FACTORY) SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = BEAN_NAME_HOG_TRANSACTION_MANAGER)
    @Primary
    public DataSourceTransactionManager hogTransactionManager(@Qualifier(BEAN_NAME_HOG_DATASOURCE) DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}